﻿using System;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;

using System.Collections.Generic;
using System.Drawing;

using System.Collections;
using System.ComponentModel;
using System.Security.Permissions;
using System.Web;
using System.Web.UI.WebControls;

using System.Xml;
using System.IO;

using System.Reflection;
using System.Security.Principal;
using System.Resources;
using CaveDigital.BoardMeeting2007Lite.ServerLib;
using Microsoft.SharePoint.Utilities;
using System.Globalization;
using CaveDigital.BoardMeeting2007Lite.Minutes.Resources;
using CaveDigital.SharedLib;
using System.Text;

namespace CaveDigital.BoardMeeting2007Lite.Minutes
{
    [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    [Guid("3fad61c5-2048-46fb-9f56-54eee77f191b")]
    public class Minute : System.Web.UI.WebControls.WebParts.WebPart
    {


        #region ATTRIBUTES PRIVATE
        bool _minuteGenerated;
        bool _minuteGenerationError;
        string _minuteDocUrl;
        private const string QUERY_CALENDARLIST_P1 = "<Where><Eq><FieldRef Name=\"";
        private const string QUERY_CALENDARLIST_P2 = "\" /><Value Type=\"Text\">";
        private const string QUERY_CALENDARLIST_P3 = "</Value></Eq></Where>";
        protected ImageButton ImageAgenda = new ImageButton();
        #endregion

        #region PROPERTIES PRIVATE
        private bool Generated
        {
            get { return _minuteGenerated; }
            set 
            { 
                _minuteGenerated = value;
                if (value)
                    _minuteGenerationError = false;
            }
        }

        private bool GenerationError
        {
            get { return _minuteGenerationError; }
            set
            {
                _minuteGenerationError = value;
                DocUrl = null;
            }
        }

        private string DocUrl
        {
            get { return _minuteDocUrl;}
            set { _minuteDocUrl = value;}
        }
        #endregion

        #region FUNCTIONS PRIVATE
        
        private SPFolder GetTemplateFolder(SPWeb web,string listName)
        {
            string docUrl = null;
            SPList list = null;
            SPContentType cType = null;
            if (web != null)
            {
                list = web.Lists[listName];
                if (list == null)
                    return null;
                cType = list.ContentTypes[Localization.GetCollectionObjectsString(Localization.RESOURCES_CAPTION_COUNCILMEETINGS_MINUTES_TEMPLATE_KEY)];
                if (cType == null)
                    return null;
                docUrl = cType.DocumentTemplateUrl;
                return web.GetFolder(docUrl.Substring(0, docUrl.IndexOf(cType.DocumentTemplate)));
            }
            return null;
        }

        private string GetHtmlLinkSeeMinute()
        {
            if (DocUrl != null)
                return string.Format("<a href=\"{0}\" target=\"_blank\">{1}</a>", DocUrl, Locals.LocalizationGetResource(MinutesConstants.RESOURCES_MESSAGE_MINUTEVIEW));
            return string.Empty;
        }
        private string PoweredByCave()
        {
            return string.Format("<div style=\"text-align:right; padding-bottom:5px; padding-left:5px; padding-right:5px; padding-top:5px;\"><a style=\"color:Gray; font-family:Verdana; font-size:10px;\" href=\"http://www.cavedigital.com/bm/\" target=\"_blank\">Developed by: CaveDigital</a></div>");
        }

        private string CaveText()
        {
            return string.Format("<div style=\"text-align:left; padding-bottom:5px; padding-left:5px; padding-right:5px; padding-top:5px;\"><a style=\"color:Gray; font-family:Verdana; font-size:10px;\">This solution is built on CaveDigital Board Meeting 2007 Lite</a></div>");
        }

        #endregion

        #region Default
        public Minute()
        {
            this.ExportMode = WebPartExportMode.All;
        }

        private void InitializeEvents()
        {
            this.ImageAgenda.Click += new ImageClickEventHandler(this.ImageAgenda_Click);
        }

        protected override void OnInit(EventArgs e)
        {
            try
            {
                this.Controls.Add(ImageAgenda);
                InitializeControls();
            }
            catch (Exception) { }
        }

        private void InitializeControls()
        {
            try
            {
                InitializeEvents();
            }
            catch (Exception)
            {
                SPUtility.Redirect(SPUtility.ErrorPage, SPRedirectFlags.Default, Context);
            }
        }

        protected override void Render(HtmlTextWriter writer)
        {
            try
            {
                SPWeb web = Wss30.GetContextWeb();   
                bool isMember = web.CurrentUser.IsSiteAdmin;
                ImageAgenda.ImageUrl = Page.ClientScript.GetWebResourceUrl(this.GetType(), ServerLib.MinutesConstants.RESOURCES_IMGS_GENERATEMINUTE);
                WindowsIdentity currentUser = WindowsIdentity.GetCurrent();
            
                if(currentUser.IsAuthenticated)
                {
                    if (!isMember)
                        for (int i = 0; i < SPContext.Current.Web.CurrentUser.Groups.Count; i++)
                            if (web.CurrentUser.Groups[i].Name == Localization.GetRoleString(Roles.Secretaries))
                            {
                                isMember = true;
                                break;
                            }
                    if(isMember)
                    {
                        CFuncs.SingleLineTable2TextWriter(writer);
                        ImageAgenda.RenderControl(writer);
                        CFuncs.HtmlTag2TextWriter(writer, HtmlTags.td, true);
                        CFuncs.HtmlTag2TextWriter(writer, HtmlTags.td);
                        if (Generated)
                            CFuncs.String2TextWriter(writer, Locals.LocalizationGetResource(MinutesConstants.RESOURCES_MESSAGE_MINUTECREATED_KEY));
                        else
                        {
                            if (GenerationError)
                                CFuncs.String2TextWriter(writer, Locals.LocalizationGetResource(MinutesConstants.RESOURCES_MESSAGE_MINUTENOTCREATED_KEY));
                            else
                                CFuncs.String2TextWriter(writer, Locals.LocalizationGetResource(MinutesConstants.RESOURCES_MESSAGE_CREATEMINUTE_KEY));
                        }
                        CFuncs.HtmlTag2TextWriter(writer, HtmlTags.td,true);
                        CFuncs.HtmlTag2TextWriter(writer, HtmlTags.tr, true);
                        if (!Common.IsNullOrEmpty<string>(DocUrl))
                        {
                            CFuncs.HtmlTag2TextWriter(writer, HtmlTags.tr);
                            CFuncs.String2TextWriter(writer, "<td colspan=\"2\">");
                            CFuncs.String2TextWriter(writer, GetHtmlLinkSeeMinute());
                            CFuncs.HtmlTag2TextWriter(writer, HtmlTags.td, true);
                            CFuncs.HtmlTag2TextWriter(writer, HtmlTags.tr,true);
                        }
                        CFuncs.HtmlTag2TextWriter(writer, HtmlTags.table,true);
                    }
                    CFuncs.String2TextWriter(writer, PoweredByCave());
                    CFuncs.String2TextWriter(writer, CaveText());
                }
            }
            catch (Exception)
            {
                CFuncs.SingleLineTableWithContent2TextWriter(writer, Locals.LocalizationGetResource(MinutesConstants.RESOURCES_MESSAGE_ERROR_KEY));
            }
        }
        #endregion

        #region Main Functions
        public bool GenerateMinute()
        {
            string bogus;
            return GenerateMinute(out bogus);
        }
        public bool GenerateMinute(out string minuteDocUrl)
        {
            minuteDocUrl = null;
            try
            {
                #region Declarations
                bool result;
                string mayorName = null;
                string docGenerationErroMsg;
                SPWeb meetingWeb = Wss30.GetContextWeb();
                SPWeb parentWeb = null;
                SPList proposalsList;
                SPList participantsList;
                SPList calendarList;
                SPList minutesDocLib;
                SPListItemCollection qryResults;
                SPFolder templateFolder;
                SPFile minutesTemplate;
                SPFile generatedFile;
                DateTime? startDatetime;
                DateTime? endDatetime;
                //Containers
                Meeting meeting;
                List<Participant> participants;
                List<Proposal> proposals;
                //Objects
                Participant participant;
                Proposal proposal;
                #endregion
                #region object init validations
                if (meetingWeb == null)
                    return false;
                parentWeb = meetingWeb.ParentWeb;
                if (parentWeb == null)
                    return false;
                proposalsList = Wss30.GetList(meetingWeb, Localization.GetMeetingSiteString(MeetingSiteObjects.AgendaDocLib));
                if (proposalsList == null)
                    return false;
                participantsList = Wss30.GetList(meetingWeb,Localization.GetMeetingSiteString(MeetingSiteObjects.ParticipantsList));
                if(participantsList == null)
                    return false;
                calendarList = Wss30.GetList(parentWeb, Localization.GetMeetingsPortalString(MeetingsPortalObjects.CalendarList));
                if (calendarList == null)
                    return false;
                #endregion
                proposals = new List<Proposal>();
                participants = new List<Participant>();
                string meetingSiteName = Wss30.EscapeSpecialCharacters(Localization.GetListColumn(MinutesConstants.RESOURCES_QRYINAME_MEETINGSPORTAL_SITE_NAME));
                #region Obtains the start and end date for the meeting
                qryResults = calendarList.GetItems(
                    Wss30.BuildQuery(
                        string.Format("{0}{1}{2}{3}{4}",
                        QUERY_CALENDARLIST_P1,
                        Wss30.EscapeSpecialCharacters(meetingSiteName),
                        QUERY_CALENDARLIST_P2,
                        Common.UriStringNormalizer(meetingWeb.Url),
                        QUERY_CALENDARLIST_P3)
                    )
                );
                if (qryResults==null || qryResults.Count == 0)
                    return false;
                startDatetime = DateTime.Parse(qryResults[0][Localization.GetListColumn(MinutesConstants.RESOURCES_INAME_MEETINGSPORTAL_STARTDATETIME_KEY)].ToString());
                endDatetime = DateTime.Parse(qryResults[0][Localization.GetListColumn(MinutesConstants.RESOURCES_INAME_MEETINGSPORTAL_ENDDATETIME_KEY)].ToString());
                #endregion
                #region Obtains the data for the participants
                for (int i = 0; i < participantsList.Items.Count; i++)
                {
                    if (participantsList.Items[i][Localization.GetListColumn(MinutesConstants.RESOURCES_CAPTION_PARTICIPANTS_NAME_KEY)] != null)
                    {
                        participant = new Participant();
                        //Obtains the name of the mayor
                        if (participantsList.Items[i][Localization.GetListColumn(MinutesConstants.RESOURCES_CAPTION_PARTICIPANTS_ROLE_KEY)] != null &&
                            participantsList.Items[i][Localization.GetListColumn(MinutesConstants.RESOURCES_CAPTION_PARTICIPANTS_ROLE_KEY)].ToString() == Localization.GetRoleString(Roles.Mayor))
                            mayorName = participantsList.Items[i].Title;
                        //Common participant data
                        participant.Name = participantsList.Items[i].Title;
                        participant.Role = participantsList.Items[i][Localization.GetListColumn(MinutesConstants.RESOURCES_CAPTION_PARTICIPANTS_ROLE_KEY)].ToString();
                        participants.Add(participant);
                    }
                }
                #endregion
                #region Obtains the data for the voting
                for (int i = 0; i < proposalsList.Items.Count; ++i)
                {
                    proposal = new Proposal();
                    proposal.Name = proposalsList.Items[i][Localization.GetListColumn(MinutesConstants.RESOURCES_CAPTION_MEETINGAGENDA_NAME_KEY)] != null ?
                        Common.FilenameRemoveExtension(proposalsList.Items[i][Localization.GetListColumn(MinutesConstants.RESOURCES_CAPTION_MEETINGAGENDA_NAME_KEY)].ToString()) : string.Empty;

                    //Checks if proposal is voted, to get voting data
                    if (proposalsList.Items[i][GlobalConstants.MEETINGSITE_DOCLIB_MEETINGAGENDA_COL_ISVOTED] != null &&
                        bool.TryParse(proposalsList.Items[i][GlobalConstants.MEETINGSITE_DOCLIB_MEETINGAGENDA_COL_ISVOTED].ToString(), out result) && result)
                    {
                        //Obtains voting count 
                        if (proposalsList.Items[i][GlobalConstants.MEETINGSITE_DOCLIB_MEETINGAGENDA_COL_VOTESINFAVOR] != null
                                    && proposalsList.Items[i][GlobalConstants.MEETINGSITE_DOCLIB_MEETINGAGENDA_COL_VOTESAGAINST] != null
                                    && proposalsList.Items[i][GlobalConstants.MEETINGSITE_DOCLIB_MEETINGAGENDA_COL_VOTESABSTAIN] != null)
                        {
                            proposal.VotesFavor = int.Parse(proposalsList.Items[i][GlobalConstants.MEETINGSITE_DOCLIB_MEETINGAGENDA_COL_VOTESINFAVOR].ToString());
                            proposal.VotesAgainst = int.Parse(proposalsList.Items[i][GlobalConstants.MEETINGSITE_DOCLIB_MEETINGAGENDA_COL_VOTESAGAINST].ToString());
                            proposal.VotesAbstain = int.Parse(proposalsList.Items[i][GlobalConstants.MEETINGSITE_DOCLIB_MEETINGAGENDA_COL_VOTESABSTAIN].ToString());
                        }
                        //Checks to see if the mayor decided the voting
                        if (proposalsList.Items[i][GlobalConstants.MEETINGSITE_DOCLIB_MEETINGAGENDA_COL_MAYORDECIDED] != null)
                            proposal.MayorDecided = bool.Parse(proposalsList.Items[i][GlobalConstants.MEETINGSITE_DOCLIB_MEETINGAGENDA_COL_MAYORDECIDED].ToString());
                        //Obtains the result of the voting
                        if (proposalsList.Items[i][GlobalConstants.MEETINGSITE_DOCLIB_MEETINGAGENDA_COL_PROPOSALRESULT] != null)
                            proposal.Result = proposalsList.Items[i][GlobalConstants.MEETINGSITE_DOCLIB_MEETINGAGENDA_COL_PROPOSALRESULT].ToString();
                    }
                    proposals.Add(proposal);
                }
                #endregion
                meeting = new Meeting(meetingWeb.Title, mayorName, proposals, participants,startDatetime,endDatetime);
                templateFolder = GetTemplateFolder( parentWeb ,Localization.GetCollectionObjectsString(Localization.RESOURCES_CAPTION_COUNCILMEETINGS_MINUTES_KEY));
                if (templateFolder == null || templateFolder.Files.Count == 0)
                    return false;
                //The minute template must be the first file
                minutesTemplate = templateFolder.Files[0];
                //Open the minutes list
                minutesDocLib = Wss30.GetList(parentWeb,Localization.GetMeetingsPortalString(MeetingsPortalObjects.MeetingMinutesDocLib));
                if(minutesDocLib == null)
                    return false;
                if (!Exporter.Export2DocLib(meeting.ExportToXmlDocument(), minutesDocLib, minutesTemplate, meetingWeb.Title, out docGenerationErroMsg, out generatedFile))
                    return false;
                minuteDocUrl = Common.UriCombine(parentWeb.Url, generatedFile.Url);
                return true;
            }
            catch (Exception) { }
            return false;
        }
        #endregion

        #region Events
        private void ImageAgenda_Click(object sender, EventArgs eventArgs)
        {
            string minuteDocUrl;
            try
            {
                SPSecurity.RunWithElevatedPrivileges(delegate()
                    {
                        if (!GenerateMinute(out minuteDocUrl))
                            GenerationError = true;
                        else
                        {
                            Generated = true;
                            DocUrl = minuteDocUrl;
                        }
                    }
                );
            }
            catch (Exception) { }
        }       
        #endregion
    }    
}